package cn.tedu.v3_1;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 *Version 3.1 多人聊天室+QQ聊天
 * 优化空间：代码结构、流没有关闭
 * 代码结构优化：1.包改变通配结构
 *            2.Server端结构
 *            ①传入数据变成静态属性方式----私有化当前类中
 *            优势：2.1 静态常量私有属性
 *            2.2 静态常量私有属性，本类任意调取
 *            2.3 Integer 使用包装类，获取包装类方法：解析
 *                自动拆装箱  Integer=4545  ==  int =4545
 *             ②ClientHandler  多线程：处理多个客户端类
 *             构造器---对象创建--完成三项事情：
 *             1.确定连接的客户端是谁
 *             2.确定链接客户端的IP是多少
 *             3.确定每个客户端都可以进行读写
 *             4.流作用域：关闭
 */
public class Server  {
    private  ServerSocket serverSocket;
    //优化：将动态添加值，提升到当前类上，变成私有化属性测试
    private static  final Integer PORT=4545;
    public Server () {
        try  {

        serverSocket=new ServerSocket(PORT);
        }  catch (BindException e) {
        System.out.println("端口号重复申请，建议换个端口号");
        } catch (IOException e)  {
        System.out.println("申请端口号失败....");
        }
    }
    public void start () {
        try {
             while(true) {
             System.out.println("----等待客户端链接-----");
             Socket socket = serverSocket.accept();
             String ip = socket.getInetAddress().getHostAddress();
             System.out.println(ip + "客户端链接成功了");
             new Thread(new ClientHandler (socket)).start();
            }
        }  catch (IOException e) {
        System.out.println("服务器端通讯断开了");
        } finally {
        if (serverSocket!=null&&!serverSocket.isClosed()){
        try {
             serverSocket.close();
          }  catch (IOException e) {
             System.out.println("服务器关闭失败");
          }
       }
    }
    }

 public static void main(String[] args) {
        new Server().start();
    }
//CS     ClientHandler  多线程内部类：处理多个客户端连接
     private class ClientHandler  implements Runnable{
     private Socket socket;
     private String ip;
    private BufferedReader br;//3.1输入流：私有化--本类任意调取
    private PrintWriter pw;
    public ClientHandler (Socket s){
    this.socket=s;//1.确定链接客户端是谁
    ip=socket.getInetAddress().getHostAddress();//2.客户端IP
            //3.每个客户端都可以进行读写
    try {
     br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
     pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF8")),true);
     } catch (IOException e) {
     e.printStackTrace();
     }
    }
    public void run() {

    try {
        new Thread(()->{
       try {
            String message;
           while((message=br.readLine())!=null){
          System.out.println("客户端说："+message);
              //增加写出一句话：读完卡住等待输入
            System.out.println("服务器请输入：");
             }
           } catch (IOException e) {
              System.out.println("客户端读入失败！");
              }
            }).start();

                Scanner input =new Scanner(System.in);
                while (true) {
                    System.out.println("服务器请输入：");
                    String say=input.nextLine();
                    pw.println("服务器说："+say);
                }
            }  catch (NullPointerException e){
                System.out.println("IO流传入对象，" +
                        "有对象为null！立马核对，" +
                        "建议：查看try块中对象可能赋值为null");
            } finally {
                //输入流关闭
               if(br!=null)
                    try {
                        br.close();
                    }  catch (IOException e) {
                        System.out.println("结束通讯：关闭失败！");
                    }
               //输出流关闭
                if(pw!=null)pw.close();
                if(socket!=null&&!socket.isClosed())
                    try {
                        socket.close();
                    } catch (IOException e) {
                        System.out.println("通讯关闭失败~");
                    }
            }
        }
    }
}
